/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "pch.h"
#include "解析运算符.h"



bool f_赋值运算符比较函数(S_运算符分割位置& a, S_运算符分割位置& b)
{
	return a.字符串位置 < b.字符串位置;
}

static void f_查找运算符在字符串位置(std::wstring& 表达式代码, const S_运算符& 运算符, std::vector<S_运算符分割位置>& 运算符位置容器) 
{
	
	uint32 num = 运算符.运算符名称.size();


	for (uint64 offset = 0;;) {
		offset = 表达式代码.find(运算符.运算符名称, offset);
		if (offset != std::wstring::npos) {
			S_运算符分割位置 pos;
			pos.字符串位置 = offset;
			pos.运算符枚举 = 运算符.赋值运算符;

			运算符位置容器.push_back(pos);

			
			for (uint32 i = 0; i < num; ++i) {
				表达式代码[i + offset] = L' ';
			}
			
		}
		else {
			break;
		}
		offset += num + 1;
	}
}

/*static void f_查找运算符在字符串位置(std::wstring& 表达式代码, const S_操作符& 操作符, const E_操作符类型& 操作符类型, std::vector<S_操作符分割位置>& 运算符位置容器)
{
	uint32 num = 操作符.符名称L.size();

	if (操作符类型 == E_操作符类型::e_访问符) {
		for (uint64 offset = 0;;) {
			offset = 表达式代码.find(操作符.符名称L, offset);

			if (offset != std::wstring::npos) {
				S_操作符分割位置 pos;
				pos.字符串位置begin = offset;
				pos.符ID = 操作符.符ID;

				运算符位置容器.push_back(pos);

				for (uint32 i = 0; i < num; ++i) {
					表达式代码[i + offset] = L' ';
				}

			}
			else {
				break;
			}
			offset += num + 1;
		}


	}
	else if (操作符类型 == E_操作符类型::e_type_三目运算符) {

	}
	else {
		for (uint64 offset = 0;;) {
			offset = 表达式代码.find(操作符.符名称L, offset);

			if (offset != std::wstring::npos) {
				S_操作符分割位置 pos;
				pos.字符串位置begin = offset;
				pos.符ID = 操作符.符ID;

				运算符位置容器.push_back(pos);

				for (uint32 i = 0; i < num; ++i) {
					表达式代码[i + offset] = L' ';
				}

			}
			else {
				break;
			}
			offset += num + 1;
		}
	}

}*/


static void f_括号递归位置查找运(std::wstring& 表达式代码, std::vector<S_操作符分割位置>& 运算符位置容器) {
	
	for (uint64 offset = 0;;) {
		offset = 表达式代码.find(L'(', offset);

		offset = 表达式代码.find(L')', offset);

	}

}

static uint32 f_括号递归位置查找运(const std::wstring& 表达式代码, S_括号代码块& 代码块, uint32 offset) {
	uint32 num = 表达式代码.size();

	for (; offset < num; ++offset) {
		
		if (表达式代码[offset] == L'{') {
			代码块.块.push_back({});

			代码块.符.符ID = 1;
			代码块.符.字符串位置begin = offset;
			offset = f_括号递归位置查找运(表达式代码, 代码块.块.back(), ++offset);
			代码块.符.字符串位置end = offset;
			
			continue;
		}
		if (表达式代码[offset] == L'}') {
			return ++offset;
		}




		if (表达式代码[offset] == L'[') {
			代码块.块.push_back({});

			代码块.符.符ID = 2;
			代码块.符.字符串位置begin = offset;
			offset = f_括号递归位置查找运(表达式代码, 代码块.块.back(), ++offset);
			代码块.符.字符串位置end = offset;

			continue;
		}
		if (表达式代码[offset] == L']') {
			return ++offset;
		}




		if (表达式代码[offset] == L'(') {
			代码块.块.push_back({});

			代码块.符.符ID = 3;
			代码块.符.字符串位置begin = offset;
			offset = f_括号递归位置查找运(表达式代码, 代码块.块.back(), ++offset);
			代码块.符.字符串位置end = offset;
			
			continue;
		}
		if (表达式代码[offset] == L')') {
			return ++offset;
		}


	}

	return offset;
}



/*std::vector<S_运算符> f_表达式解析赋值运算符(std::wstring& 表达式代码)
{
	std::vector<S_运算符> 返回字符;
	std::vector<S_运算符分割位置> 运算符位置;

	auto 运算符枚举 = f_赋值运算符枚举(E_操作符类型::e_赋值运算符);
	for (auto& e : 运算符枚举) {
		f_查找运算符在字符串位置(表达式代码, e, 运算符位置);
	}
	
	sort(运算符位置.begin(), 运算符位置.end(), f_赋值运算符比较函数);

    return 返回字符;
}*/





S_括号代码块 f_括号表达式解析(std::wstring& 表达式代码)
{
	uint32 类型状态 = 0;
	uint32 num = 表达式代码.size();
	//uint64 offset = 0;
	S_括号代码块 代码块;

	for (uint64 offset = 0; offset < num; ++offset) {
		offset = f_括号递归位置查找运(表达式代码, 代码块, offset);
	}
	

	//auto code = 表达式代码.substr(代码块.符.字符串位置begin, 代码块.符.字符串位置end - 代码块.符.字符串位置begin);
	//f_查找运算符在字符串位置(表达式代码, , , );
	return 代码块;
}



std::vector<S_运算符> f_运算符枚举(E_运算符优先级 优先级)
{
	switch (优先级)
	{
	case E_运算符优先级::e_运算符_L1: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_指针, L"->" },
			{ E_运算符::e_成员, L"." },
		};
		return 运算符;
	}
	
	case E_运算符优先级::e_运算符_L2: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_取负, L"!" },
			{ E_运算符::e_非, L"!" },
			{ E_运算符::e_按位取反, L"~" },
			{ E_运算符::e_前加加, L"++" },
			{ E_运算符::e_前减减, L"--" },
		};
		return 运算符;
	}
	
	case E_运算符优先级::e_运算符_L3: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_后加加, L"++" },
			{ E_运算符::e_后减减, L"--" },
			//{ E_算术运算符L2::e_类型转换, L")*" },
			{ E_运算符::e_取指针, L"&" },
			{ E_运算符::e_类型大小, L"sizeof" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L4: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_乘, L"*" },
			{ E_运算符::e_除, L"/" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L5: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_加, L"+" },
			{ E_运算符::e_减, L"-" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L6: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_左移, L"<<" },
			{ E_运算符::e_右移, L">>" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L7: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_小于, L"<" },
			{ E_运算符::e_小于等于, L"<=" },
			{ E_运算符::e_大于, L">" },
			{ E_运算符::e_大于等于, L">=" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L8: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_等于, L"==" },
			{ E_运算符::e_不等于, L"!=" },
		};
	}

	case E_运算符优先级::e_运算符_L9: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_按位与, L"&" },
		};
	}

	case E_运算符优先级::e_运算符_L10: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_异或, L"^" },
		};
	}

	case E_运算符优先级::e_运算符_L11: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_按位或, L"|" },
		};
	}

	case E_运算符优先级::e_运算符_L12: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_逻辑且, L"&&" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L13: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_逻辑或, L"||" },
		};
		return 运算符;
	}

	case E_运算符优先级::e_运算符_L14: {
		static std::vector<S_运算符> 运算符 =
		{
			{ E_运算符::e_三目运算符, L"?" },
		};
		break;
	}

	case E_运算符优先级::e_运算符_L15: {
		static std::vector<S_运算符> 运算符 =
		{

			{ E_运算符::e_加等于, L"+=" },
			{ E_运算符::e_减等于, L"-=" },
			{ E_运算符::e_乘等于, L"*=" },
			{ E_运算符::e_除等于, L"/=" },
			{ E_运算符::e_余等于, L"%=" },
			{ E_运算符::e_左移等于, L"<<=" },
			{ E_运算符::e_右移等于, L">>=" },
			{ E_运算符::e_且等于, L"&=" },
			{ E_运算符::e_或等于, L"|=" },
			{ E_运算符::e_异或等于, L"^=" },
			{ E_运算符::e_赋值, L"=" },
		};
		return 运算符;
	}
	default:
		break;
	}

	return {};
}

/*std::map<E_赋值运算符, std::wstring> f_赋值运算符枚举map()
{
	static std::map<E_赋值运算符, std::wstring> 运算符 =
	{
		
		{ E_赋值运算符::e_加等于, L"+=" },
		{ E_赋值运算符::e_减等于, L"-=" },
		{ E_赋值运算符::e_乘等于, L"*=" },
		{ E_赋值运算符::e_除等于, L"/=" },
		{ E_赋值运算符::e_余等于, L"%=" },
		{ E_赋值运算符::e_左移等于, L"<<=" },
		{ E_赋值运算符::e_右移等于, L">>=" },
		{ E_赋值运算符::e_且等于, L"&=" },
		{ E_赋值运算符::e_或等于, L"|=" },
		{ E_赋值运算符::e_异或等于, L"^=" },
		{ E_赋值运算符::e_赋值, L"=" },
	};

	return 运算符;
}*/

std::vector<S_运算符分割位置> f_表达式解析运算符位置(std::wstring& 表达式代码, E_运算符优先级 优先级)
{
	auto 运算符字符枚举 = f_运算符枚举(优先级);
	std::vector<S_运算符分割位置> 运算符位置;

	for (auto& e : 运算符字符枚举) {
		f_查找运算符在字符串位置(表达式代码, e, 运算符位置);
	}
	sort(运算符位置.begin(), 运算符位置.end(), f_赋值运算符比较函数);

	return 运算符位置;
}

static std::vector<S_操作符表达段> f_表达式分割到词(
	const std::wstring& 表达式代码, 
	const std::vector<S_运算符分割位置>& 分割符合, 
	const E_运算符优先级 优先级)
{
	std::vector<S_操作符表达段> 分割后词组;

	uint32 num = 分割符合.size();
	auto data_p = 分割符合.data();

	uint32 开始位置 = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32 词字符数量 = data_p[i].字符串位置 - 开始位置;
		分割后词组.push_back({ E_运算符(data_p[i].运算符枚举), 表达式代码.substr(开始位置, 词字符数量) });
		开始位置 += 词字符数量;

		

		switch (优先级)
		{
		case E_运算符优先级::e_运算符_L1: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_指针: 开始位置 += 2; break;
			case E_运算符::e_成员: 开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L2: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_非:		开始位置 += 1; break;
			case E_运算符::e_取负:	开始位置 += 1; break;
			case E_运算符::e_前加加:	开始位置 += 2; break;
			case E_运算符::e_前减减:	开始位置 += 2; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L3: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_后加加:		开始位置 += 2; break;
			case E_运算符::e_后减减:		开始位置 += 2; break;
			//casE_运算符L2::e_类型转换:	开始位置 += 2; break;
			case E_运算符::e_取指针:		开始位置 += 1; break;
			case E_运算符::e_类型大小:	开始位置 += 6; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L4: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_乘: 开始位置 += 1; break;
			case E_运算符::e_除: 开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L5: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_加: 开始位置 += 1; break;
			case E_运算符::e_减: 开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L6: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_左移: 开始位置 += 2; break;
			case E_运算符::e_右移: 开始位置 += 2; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L7: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_小于:		开始位置 += 1; break;
			case E_运算符::e_小于等于:	开始位置 += 2; break;
			case E_运算符::e_大于:		开始位置 += 1; break;
			case E_运算符::e_大于等于:	开始位置 += 2; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L8: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_等于:	开始位置 += 2; break;
			case E_运算符::e_不等于:	开始位置 += 2; break;
			}
			break;
		}


		case E_运算符优先级::e_运算符_L9: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_按位与:		开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L10: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_异或:		开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L11: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_按位或:		开始位置 += 1; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L12: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_逻辑且:		开始位置 += 2; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L13: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_逻辑或:		开始位置 += 2; break;
			}
			break;
		}

		case E_运算符优先级::e_运算符_L14: {
			//开始位置 += 2; break;
			break;
		}

		case E_运算符优先级::e_运算符_L15: {
			switch (data_p[i].运算符枚举) {
			case E_运算符::e_加等于:		开始位置 += 2; break;
			case E_运算符::e_减等于:		开始位置 += 2; break;
			case E_运算符::e_乘等于:		开始位置 += 2; break;
			case E_运算符::e_除等于:		开始位置 += 2; break;
			case E_运算符::e_余等于:		开始位置 += 2; break;
			case E_运算符::e_左移等于:		开始位置 += 3; break;
			case E_运算符::e_右移等于:		开始位置 += 3; break;
			case E_运算符::e_且等于:		开始位置 += 2; break;
			case E_运算符::e_或等于:		开始位置 += 2; break;
			}
			break;
		}
		default:
			break;
		}

	}

	
	return 分割后词组;
}

std::vector<S_操作符表达段> f_get表达式符号和标示(std::wstring& 表达式代码, E_运算符优先级 优先级)
{
	auto 运算符 = f_表达式解析运算符位置(表达式代码, 优先级);
	if (运算符.size()) {
		return f_表达式分割到词(表达式代码, 运算符, 优先级);
	}
	return std::vector<S_操作符表达段>();
}






